<template>
  <div class="risk-index h-full grid grid-rows-[45fr_55fr] gap-15px text-white">
    <!-- 顶部：左-总体安全指数，右-风险指标运行统计 -->
    <div class="grid grid-cols-[35fr_65fr] gap-15px min-h-0">
      <!-- 左：总体安全指数 -->
      <DsPanel>
        <template #title>
          <div class="flex items-center gap-6px">
            <span>总体安全指数</span>
            <el-icon class="cursor-pointer hover:opacity-90" color="#7dcaff" @click.stop="rulesDialogVisible = true">
              <QuestionFilled />
            </el-icon>
          </div>
        </template>
        <div class="relative h-full min-h-0">
          <!-- 右上角时间切换 -->
          <div class="trend-radio absolute right-10px top-6px flex items-center gap-8px z-10">
            <button
              v-for="tab in timeTabs"
              :key="tab.value"
              class="tr-btn bg-transparent text-[#cfe6ff] text-[15px] w-[109px] h-[32px] cursor-pointer border-0"
              :class="{
                'bg-[url(/src/assets/bi_images/rectangle.png)] bg-no-repeat bg-center bg-[length:100%_100%] text-white': activeTimeTab === tab.value
              }"
              @click="activeTimeTab = tab.value"
            >
              {{ tab.label }}
            </button>
          </div>

          <!-- 内容：左侧仪表盘33%，右侧走势图 -->
          <div class="grid grid-cols-[33%_auto] gap-16px h-full min-h-0">
            <!-- 仪表盘 -->
            <div class="relative px-12px py-12px flex flex-col items-center justify-center overflow-hidden">
              <VChart class="w-full max-h-[220px] z-2" :option="gaugeOption" autoresize />
              <!-- 底部水平线 -->
              <div class="absolute left-[6%] right-[6%] top-1/2 h-[2px] bg-[rgb(96,102,113)] pointer-events-none z-1" />
            </div>

            <!-- 安全值走势折线图 -->
            <div class="px-18px py-16px flex flex-col">
              <div class="flex-1 min-h-0">
                <VChart class="w-full h-full" :option="lineOption" autoresize />
              </div>
            </div>
          </div>
        </div>
      </DsPanel>

      <!-- 右：风险指标运行统计 -->
      <DsPanel title="风险指标运行统计">
        <div class="biz-grid h-full min-h-0 flex flex-col gap-10px">
          <!-- 第一行：业绩数据卡（单独一行） -->
          <div class="grid grid-cols-4 gap-10px" style="border-bottom: 1px solid rgba(27, 126, 242, 0.3)">
            <!-- 第一项：事故事件（特殊样式） -->
            <div class="flex items-center justify-between px-14px py-5px text-[#cfe6ff] rd-8px">
              <div class="flex items-center gap-8px">
                <img class="w-[17px] h-[36px]" src="@/assets/bi_images/sgsj_1.png" alt="事故事件" />
                <span class="text-18px font-700 text-[#29F1FA] italic" style="font-family: 'Alimama ShuHeiTi', sans-serif">事故事件</span>
              </div>
              <img class="w-[15px] h-[12px]" src="@/assets/bi_images/decoration.png" alt="icon" />
            </div>

            <!-- 其他三项 -->
            <div v-for="kpi in topKpis.slice(1)" :key="kpi.label" class="flex items-center justify-between px-14px py-10px text-[#cfe6ff] rd-8px">
              <div class="flex items-center gap-8px text-14px">
                <img class="size-18px" src="@/assets/bi_images/jiantou.png" alt="jiantou" />
                <span class="opacity-80 text-16px">{{ kpi.label }}</span>
              </div>
              <div class="kpi-value text-20px font-700 text-white">{{ kpi.value }}</div>
            </div>
          </div>

          <!-- 第二部分：8个业务块 -->
          <div class="flex-1 grid grid-cols-4 gap-10px min-h-0">
            <div class="flex items-stretch justify-center h-full min-h-0" v-for="block in bizBlocks" :key="block.title">
              <BizCard
                :title="block.title"
                :icon="block.icon"
                :headers="block.headers"
                :rows="periodRows"
                :sample-fn="sampleCell"
                class="h-full min-h-0 w-[260px] overflow-hidden shrink-0"
              />
            </div>
          </div>
        </div>
      </DsPanel>
    </div>

    <!-- 底部：风险状态监测（雷达图 + 折线图） -->
    <DsPanel title="风险状态监测">
      <div class="grid grid-cols-[28fr_72fr] gap-18px h-full min-h-0">
        <!-- 左侧：雷达图 -->
        <div class="radar-card relative px-18px py-16px flex flex-col min-w-0 overflow-hidden">
          <div class="flex-1 min-h-0 relative">
            <VChart class="absolute inset-0" :option="radarOption" autoresize @click="handleRadarClick" />
          </div>
          <!-- 右上角：当前安全指数 + 指标详情图标 -->
          <div class="absolute right-10px top-10px z-10 flex items-center">
            <div
              class="w-[155px] h-[40px] bg-[url(/src/assets/bi_images/shuju.png)] bg-no-repeat bg-center bg-[length:100%_100%] flex flex-col items-center justify-center text-center"
            >
              <div class="text-[9px] text-[#cfe6ff] pb-[8px]">当前安全指数</div>
              <div class="text-[21px] font-800 text-[#60c9ff] leading-[1.1] pb-[8px]">{{ currentScore.toFixed(1) }}</div>
            </div>
            <el-icon class="ml-6px cursor-pointer hover:opacity-90" color="#7dcaff" @click.stop="detailsDialogVisible = true">
              <QuestionFilled />
            </el-icon>
          </div>
        </div>

        <!-- 右侧：近8小时安全指数走势折线图 -->
        <div class="timeline-card px-18px py-16px flex flex-col min-w-0 overflow-hidden">
          <div class="flex-1 min-h-0">
            <VChart class="w-full h-full" :option="multiLineOption" autoresize />
          </div>
        </div>
      </div>
    </DsPanel>

    <!-- 规则弹窗：计算规则表（使用 bi-dialog-big 大背景样式） -->
    <el-dialog v-model="rulesDialogVisible" title="安全指数计算规则" width="80%" class="bi-dialog-big">
      <el-table :data="rulesRows" height="80vh" :span-method="rulesSpanMethod" class="rules-table" style="width: 100%">
        <el-table-column prop="A" label="序号" width="70" align="center" />
        <el-table-column prop="B" label="指标类型" width="120" align="center" />
        <el-table-column prop="C" label="权重" width="80" align="center" />
        <el-table-column prop="D" label="安全指数名称" width="140" align="center" />
        <el-table-column label="分类" align="center">
          <el-table-column prop="E" label="" width="140" align="center" />
          <el-table-column prop="F" label="" width="140" align="center" />
        </el-table-column>
        <el-table-column prop="G" label="扣分原因" min-width="240" show-overflow-tooltip />
        <el-table-column prop="H" label="风险赋值标准（每大类百分制扣分）" min-width="360" show-overflow-tooltip />
        <el-table-column prop="I" label="说明" min-width="160" show-overflow-tooltip />
      </el-table>
    </el-dialog>

    <!-- 指标详情弹窗：风险要素计算表格（使用 bi-dialog-big 大背景样式） -->
    <el-dialog v-model="detailsDialogVisible" title="风险要素计算详情" width="70%" class="bi-dialog-big">
      <el-table
        :data="tableRows"
        height="70vh"
        stripe
        :span-method="spanMethod"
        :row-class-name="getRowClass"
        :cell-class-name="getCellClass"
        class="risk-factors-table"
        style="width: 100%"
      >
        <el-table-column prop="index" label="序号" width="70" />
        <el-table-column prop="category" label="风险要素大类" class-name="category-col" />
        <el-table-column prop="subCategory" label="风险要素小类" />
        <el-table-column prop="decision" label="否决项" />
        <el-table-column prop="reason" label="说明原因" min-width="200" show-overflow-tooltip />
        <el-table-column prop="penalty" label="扣分" align="center" width="80" />
      </el-table>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, onMounted } from 'vue';
import DsPanel from './DsPanel.vue';
import BizCard from './drill/components/BizCard.vue';
import type { ECBasicOption } from 'echarts/types/dist/shared';
import { getRiskIndexStatistics, getOverallSafetyIndexStatistics, getBusinessIndicatorsStatistics, getRiskIndicatorLine } from '@/api/ds';
import { QuestionFilled } from '@element-plus/icons-vue';
import { rulesRows as rulesRowsRaw, rulesMerges } from './rulesData';
// 业务块图标
import iconYufang from '@/assets/bi_images/yufang.png';
import iconHuilu from '@/assets/bi_images/huilu.png';
import iconKekaoxing from '@/assets/bi_images/kekaoxing.png';
import iconGongyi from '@/assets/bi_images/gongy8i.png';
import iconSis from '@/assets/bi_images/sis.png';
import iconGsd from '@/assets/bi_images/gsd.png';
import iconTeshu from '@/assets/bi_images/teshu.png';
import iconRenyuan from '@/assets/bi_images/renyuan.png';

// 风险要素大类名称映射
const categoryNameMap: Record<string, string> = {
  doublePrevention: '双重预防',
  controlCircuit: '控制回路',
  sisSide: 'SIS联锁旁路',
  processAlarm: '工艺报警',
  deviceRun: '设备可靠性',
  personAggregation: '人员聚集',
  gdsAlarm: 'GDS报警',
  specialWork: '特殊作业'
};

interface RiskRow {
  index: number;
  category: string;
  subCategory: string;
  decision: string;
  reason: string;
  penalty: number;
}

const avgIndex = ref(63);
// 本地选中的分类（支持雷达图高亮和表格过滤）
const localSelectedCategory = ref<string>('');
const totalScore = ref(100);
const currentYear = new Date().getFullYear();
const statisticsData = ref<any>(null);
const overallSafetyData = ref<any>(null);
const businessIndicatorsData = ref<any>(null);
const riskIndicatorLineData = ref<any>(null);

const timeTabs = [
  { label: '本周', value: '7d' },
  { label: '当月', value: '30d' }
] as const;

const activeTimeTab = ref<(typeof timeTabs)[number]['value']>('7d');

// 第一行业绩数据卡（从接口数据获取）
const topKpis = computed(() => {
  if (businessIndicatorsData.value?.accidentStats) {
    const stats = businessIndicatorsData.value.accidentStats;
    return [
      { label: '事故事件', value: 0 },
      { label: '近三年重大事故', value: stats.lastThreeYearsMajorAccidents || 0 },
      { label: '近两年较大事故', value: stats.lastTwoYearsSeriousAccidents || 0 },
      { label: '近一年一般事故', value: stats.lastYearGeneralAccidents || 0 }
    ];
  }
  return [
    { label: '事故事件', value: 0 },
    { label: '近三年重大事故', value: 0 },
    { label: '近两年较大事故', value: 0 },
    { label: '近一年一般事故', value: 0 }
  ];
});

// 第二、三行的 8 个业务块配置
const bizBlocks = [
  {
    icon: iconYufang,
    title: '双重预防',
    headers: ['隐患总数', '重大隐患', '未整改']
  },
  {
    icon: iconHuilu,
    title: '控制回路',
    headers: ['有效自控率']
  },
  {
    icon: iconKekaoxing,
    title: '设备可靠性',
    headers: ['检修完成率', '报警总数', '一级报警']
  },
  {
    icon: iconGongyi,
    title: '工艺报警',
    headers: ['操作平稳率', '报警总数', 'A类报警']
  },
  {
    icon: iconSis,
    title: 'SIS连锁旁路',
    headers: ['旁路数量']
  },
  {
    icon: iconGsd,
    title: 'GDS报警',
    headers: ['总数', '可燃', '有毒']
  },
  {
    icon: iconTeshu,
    title: '特殊作业',
    headers: ['总数', '动火', '受限', '高处', '吊装']
  },
  {
    icon: iconRenyuan,
    title: '人员聚集',
    headers: ['红色报警', '橙色报警', '黄色报警']
  }
] as const;

const periodRows = ['近7天', '近30天', '当年'] as const;

// 动态得分：根据选中的要素大类显示对应分值
const currentScore = computed(() => {
  if (!statisticsData.value) return avgIndex.value;

  // 如果有选中的要素大类，显示该大类的得分
  if (localSelectedCategory.value && localSelectedCategory.value !== '') {
    const categoryData = statisticsData.value[localSelectedCategory.value];
    if (categoryData && typeof categoryData === 'object' && 'score' in categoryData) {
      return parseFloat(categoryData.score) || 0;
    }
  }

  // 否则显示当前安全指数
  return parseFloat(statisticsData.value.indexScore) || avgIndex.value;
});

// 计算表格数据
const tableRows = computed<RiskRow[]>(() => {
  if (!statisticsData.value) return [];

  const rows: RiskRow[] = [];
  let index = 1;

  // 如果有选中分类，则只保留该分类的数据
  const selectedForFilter = localSelectedCategory.value || '';

  // 遍历所有风险要素大类
  Object.entries(statisticsData.value).forEach(([key, categoryData]) => {
    // 跳过非风险要素字段
    if (key === 'indexScore' || key === 'totalScore') return;

    // 若存在选中分类，则只保留该分类的数据
    if (selectedForFilter && key !== selectedForFilter) return;

    const categoryName = categoryNameMap[key] || key;

    // 遍历该大类下的所有子项
    categoryData.riskSubItemVos?.forEach((subItem: any) => {
      rows.push({
        index: index++,
        category: categoryName,
        subCategory: subItem.subTypeName,
        decision: subItem.isNegated === 1 ? '是' : '否',
        reason: subItem.deductionReason || '',
        penalty: parseFloat(subItem.deductionScore) || 0
      });
    });
  });

  return rows;
});

// 表格合并单元格函数
const spanMethod = ({ row, column, rowIndex, columnIndex }: any) => {
  if (columnIndex === 1) {
    // 风险要素大类列
    const currentCategory = row.category;
    let rowspan = 1;
    const colspan = 1;

    // 查找相同类别的连续行数
    for (let i = rowIndex + 1; i < tableRows.value.length; i++) {
      if (tableRows.value[i].category === currentCategory) {
        rowspan++;
      } else {
        break;
      }
    }

    // 检查是否是该类别的第一行
    if (rowIndex === 0 || tableRows.value[rowIndex - 1].category !== currentCategory) {
      return { rowspan, colspan };
    } else {
      return { rowspan: 0, colspan: 0 };
    }
  }
  return { rowspan: 1, colspan: 1 };
};

// 表格行样式函数
const getRowClass = ({ row }: any) => {
  if (localSelectedCategory.value && categoryNameMap[localSelectedCategory.value] === row.category) {
    return 'highlighted-row';
  }
  return '';
};

// 表格单元格样式函数：确保合并后的"大类"单元格整体高亮
const getCellClass = ({ row, column }: any) => {
  if (column?.property === 'category') {
    if (localSelectedCategory.value && categoryNameMap[localSelectedCategory.value] === row.category) {
      return 'highlighted-category-cell';
    }
  }
  return '';
};

// 从接口数据获取单元格数据
function sampleCell(blockTitle: string, header: string, row: string) {
  if (!businessIndicatorsData.value) {
    // 如果没有数据，返回默认值
    return '-';
  }

  // 映射行标签到数据字段
  const periodMap: Record<string, string> = {
    '近7天': 'last7Days',
    '近30天': 'last30Days',
    '当年': 'currentYear'
  };

  // 映射业务块到数据字段
  const blockMap: Record<string, string> = {
    '双重预防': 'doublePrevention',
    '控制回路': 'controlLoop',
    '设备可靠性': 'deviceRun',
    '工艺报警': 'processAlarm',
    'SIS连锁旁路': 'sisSide',
    'GDS报警': 'gdsAlarm',
    '特殊作业': 'specialWork',
    '人员聚集': 'personAggregation'
  };

  const periodKey = periodMap[row];
  const blockKey = blockMap[blockTitle];

  if (!periodKey || !blockKey) return '-';

  const blockData = businessIndicatorsData.value[blockKey];
  if (!blockData || !blockData[periodKey]) return '-';

  const periodData = blockData[periodKey];

  // 根据业务块和表头映射到具体字段
  const headerFieldMap: Record<string, Record<string, string>> = {
    '双重预防': {
      '隐患总数': 'totalHiddenDangers',
      '重大隐患': 'majorHiddenDangers',
      '未整改': 'unRectifiedCount'
    },
    '控制回路': {
      '有效自控率': 'effectiveControlRate'
    },
    '设备可靠性': {
      '检修完成率': 'maintenanceCompletionRate',
      '报警总数': 'totalAlarms',
      '一级报警': 'levelOneAlarms'
    },
    '工艺报警': {
      '操作平稳率': 'operationStabilityRate',
      '报警总数': 'totalAlarms',
      'A类报警': 'aclassAlarms'
    },
    'SIS连锁旁路': {
      '旁路数量': 'bypassCount'
    },
    'GDS报警': {
      '总数': 'totalAlarms',
      '可燃': 'combustibleAlarms',
      '有毒': 'toxicAlarms'
    },
    '特殊作业': {
      '总数': 'total',
      '动火': 'fireWork',
      '受限': 'spaceWork',
      '高处': 'elevationWork',
      '吊装': 'hoistingWork'
    },
    '人员聚集': {
      '红色报警': 'redLevel',
      '橙色报警': 'orangeLevel',
      '黄色报警': 'yellowLevel'
    }
  };

  const fieldMap = headerFieldMap[blockTitle];
  if (!fieldMap) return '-';

  const fieldKey = fieldMap[header];
  if (!fieldKey) return '-';

  const value = periodData[fieldKey];
  if (value === undefined || value === null) return '-';

  // 如果是比率，转换为百分比
  if (header.includes('率')) {
    return `${Math.round(value * 100)}%`;
  }

  return value.toString();
}

// 雷达点击：切换高亮分类；重复点击同一分类则清空高亮并恢复表格
function handleRadarClick(params: any) {
  console.log('Radar click params:', params);

  const titleToKey: Record<string, string> = {
    双重预防: 'doublePrevention',
    控制回路: 'controlCircuit',
    设备可靠性: 'deviceRun',
    工艺报警: 'processAlarm',
    SIS连锁旁路: 'sisSide',
    GDS报警: 'gdsAlarm',
    特殊作业: 'specialWork',
    人员聚集: 'personAggregation'
  };

  let key: string | undefined;

  // 点击雷达图的label（axisName）
  if (params?.componentType === 'radar' && params?.name) {
    // 从富文本格式化后的name中提取标题
    const fullName = params.name;

    // 处理富文本格式：{selected|标题} 或 {normal|标题}
    let title = '';
    const richTextMatch = fullName.match(/\{(?:selected|normal)\|([^}]+)\}/);
    if (richTextMatch) {
      title = richTextMatch[1];
    } else {
      // 如果不是富文本格式，直接提取第一行
      title = fullName.split('\n')[0];
      // 移除可能的选中标记
      if (title.startsWith('[*]')) {
        title = title.substring(3);
      }
    }

    key = titleToKey[title];
  }
  // 点击雷达系列（series）
  else if (params?.componentType === 'series' && params?.seriesType === 'radar') {
    // 点击的是雷达图区域，也触发选中
    return;
  }

  if (!key) {
    console.log('Key not found for title');
    return;
  }

  console.log('Current localSelectedCategory:', localSelectedCategory.value);
  console.log('Clicked key:', key);

  if (localSelectedCategory.value === key) {
    // 再次点击同一个分类，清空高亮
    console.log('Clearing selection');
    localSelectedCategory.value = '';
  } else {
    // 选中新的分类
    console.log('Setting selection to:', key);
    localSelectedCategory.value = key;
  }
}

// 获取风险指数统计数据
const fetchRiskIndexStatistics = async () => {
  try {
    const response = await getRiskIndexStatistics();
    statisticsData.value = response.data;

    // 更新当前安全指数
    if (statisticsData.value?.indexScore) {
      avgIndex.value = parseFloat(statisticsData.value.indexScore) || 63;
    }
  } catch (error) {
    console.error('获取风险指数统计数据失败:', error);
  }
};

// 获取总体安全指数统计数据
const fetchOverallSafetyIndexStatistics = async () => {
  try {
    const response = await getOverallSafetyIndexStatistics();
    overallSafetyData.value = response.data;
  } catch (error) {
    console.error('获取总体安全指数统计数据失败:', error);
  }
};

// 获取风险指标运行统计数据
const fetchBusinessIndicatorsStatistics = async () => {
  try {
    const response = await getBusinessIndicatorsStatistics();
    businessIndicatorsData.value = response.data;
  } catch (error) {
    console.error('获取风险指标运行统计数据失败:', error);
  }
};

// 获取近8小时安全指数折线图数据
const fetchRiskIndicatorLine = async () => {
  try {
    const response = await getRiskIndicatorLine();
    riskIndicatorLineData.value = response.data;
  } catch (error) {
    console.error('获取近8小时安全指数折线图数据失败:', error);
  }
};

function createGradient(colors: [string, number][]): any {
  const echarts = (window as any).echarts as { graphic: { LinearGradient: new (...args: unknown[]) => unknown } } | undefined;
  if (!echarts) {
    return {
      type: 'linear',
      x: 0,
      y: 0,
      x2: 0,
      y2: 1,
      colorStops: colors.map(([color, offset]) => ({ color, offset }))
    } as const;
  }
  return new echarts.graphic.LinearGradient(
    0,
    0,
    0,
    1,
    colors.map(([color, offset]) => ({ color, offset }))
  );
}

function createGradientLR(colors: [string, number][]): any {
  const echarts = (window as any).echarts as { graphic: { LinearGradient: new (...args: unknown[]) => unknown } } | undefined;
  if (!echarts) {
    return {
      type: 'linear',
      x: 0,
      y: 0,
      x2: 1,
      y2: 0,
      colorStops: colors.map(([color, offset]) => ({ color, offset }))
    } as const;
  }
  return new echarts.graphic.LinearGradient(
    0,
    0,
    1,
    0,
    colors.map(([color, offset]) => ({ color, offset }))
  );
}

const gaugeOption = computed<ECBasicOption>(() => {
  const title = activeTimeTab.value === '7d' ? '本周平均' : '当月平均';

  // 从接口数据获取平均值
  let gaugeValue = avgIndex.value;
  if (overallSafetyData.value) {
    const avgKey = activeTimeTab.value === '7d' ? 'last7DaysAverageIndex' : 'last30DaysAverageIndex';
    gaugeValue = overallSafetyData.value[avgKey] || avgIndex.value;
  }

  const leftToRight = createGradientLR([
    ['#2a86e5', 0],
    ['#33E0FF', 0.5],
    ['#38FFD8', 1]
  ]);

  const pointerGradient = createGradientLR([
    ['rgba(56, 255, 216, 0.95)', 0],
    ['rgba(43, 210, 255, 0.85)', 0.5],
    ['rgba(43, 210, 255, 0.0)', 1]
  ]);

  return {
    backgroundColor: 'transparent',
    tooltip: { show: false },
    series: [
      // 内部半圆背景填充（与最小 gauge 同心，半径略小于 45%）
      {
        type: 'pie',
        center: ['50%', '50%'],
        radius: ['0%', '44%'],
        startAngle: 180,
        silent: true,
        hoverAnimation: false,
        label: { show: false },
        labelLine: { show: false },
        z: 1,
        data: [
          // 先绘制下半圆为透明，再绘制上半圆为背景色
          { value: 50, itemStyle: { color: 'rgb(31, 46, 68)' } },
          { value: 50, itemStyle: { color: 'rgba(0,0,0,0)' } }
        ]
      },
      {
        type: 'gauge',
        startAngle: 180,
        endAngle: 0,
        center: ['50%', '50%'],
        radius: '92%',
        axisLine: {
          lineStyle: {
            width: 10,
            color: [[1, leftToRight]],
            cap: 'round'
          }
        },
        splitLine: { show: false },
        axisTick: { show: false },
        axisLabel: { show: false },
        pointer: {
          length: '64%',
          width: 6,
          offsetCenter: [0, '-5%'],
          itemStyle: {
            color: pointerGradient,
            shadowBlur: 10,
            shadowColor: 'rgba(32, 198, 191, 0.65)'
          }
        },
        anchor: {
          show: true,
          showAbove: true,
          size: 15,
          itemStyle: {
            color: '#2FF3E0',
            shadowBlur: 18,
            shadowColor: 'rgba(32, 198, 191, 0.65)',
            borderColor: '#25f1c7',
            borderWidth: 3
          }
        },
        progress: { show: false },
        title: {
          show: true,
          offsetCenter: [0, '90%'],
          color: '#fff',
          fontSize: 14
        },
        detail: {
          show: true,
          formatter: '{value}',
          valueAnimation: true,
          color: '#60c9ff',
          fontSize: 32,
          fontWeight: 800,
          offsetCenter: [0, '55%']
        },
        data: [{ value: gaugeValue, name: title }],
        min: 0,
        z: 5
      },
      {
        type: 'gauge',
        startAngle: 180,
        endAngle: 0,
        center: ['50%', '50%'],
        radius: '75%',
        axisLine: {
          lineStyle: {
            width: 2,
            color: [[1, 'rgba(214, 192, 143, 0.35)']]
          }
        },
        splitNumber: 3,
        splitLine: {
          show: true,
          length: 3,
          distance: 0,
          lineStyle: {
            color: 'rgb(96, 102, 113)',
            width: 1
          }
        },
        axisTick: { show: false },
        axisLabel: { show: false },
        pointer: { show: false },
        anchor: { show: false },
        detail: { show: false },
        data: [{ value: 0 }],
        min: 0,
        z: 2
      },
      {
        type: 'gauge',
        startAngle: 180,
        endAngle: 0,
        center: ['50%', '50%'],
        radius: '45%',
        axisLine: {
          lineStyle: {
            width: 3,
            color: [[1, 'rgba(214, 192, 143, 0.35)']]
          }
        },
        splitLine: { show: false },
        axisTick: { show: false },
        axisLabel: { show: false },
        pointer: { show: false },
        anchor: { show: false },
        detail: { show: false },
        data: [{ value: 0 }],
        z: 2
      }
    ]
  } as ECBasicOption;
});

// 动态生成折线图数据（仅使用接口数据）
const generateLineData = (type: '7d' | '30d') => {
  if (!overallSafetyData.value) {
    return {
      labels: [],
      series: []
    };
  }

  const sourceData = type === '7d' ? overallSafetyData.value.last7Days : overallSafetyData.value.last30Days;
  const avgKey = type === '7d' ? 'last7DaysAverageIndex' : 'last30DaysAverageIndex';
  const averageValue = overallSafetyData.value[avgKey] || 0;

  if (!sourceData) {
    return {
      labels: [],
      series: []
    };
  }

  const labels = sourceData.dates || [];
  const dataPoints1 = sourceData.blue || [];
  // 紫色线：使用平均值填充整个数组（水平直线）
  const dataPoints2 = Array(labels.length).fill(averageValue);

  return {
    labels,
    series: [
      {
        name: type === '7d' ? '近7天平均指数' : '近30天平均指数',
        color: '#855afd',
        area: createGradient([
          ['rgba(132, 90, 253, 0.4)', 0],
          ['rgba(132, 90, 253, 0)', 1]
        ]),
        data: dataPoints2,
        smooth: false
      },
      {
        name: type === '7d' ? '本周数据' : '本月数据',
        color: '#43d3ff',
        area: createGradient([
          ['rgba(67, 211, 255, 0.35)', 0],
          ['rgba(67, 211, 255, 0)', 1]
        ]),
        data: dataPoints1,
        smooth: false
      }
    ]
  };
};

const lineOption = computed<ECBasicOption>(() => {
  const lineData = generateLineData(activeTimeTab.value);

  return {
    grid: { left: 30, right: 10, top: 30, bottom: 20 },
    tooltip: {
      trigger: 'axis',
      confine: true,
      appendToBody: false,
      position: (pos: number[], _params: any, dom: HTMLElement, _rect: any, size: any) => {
        const [mouseX, mouseY] = pos;
        const viewSize = size?.viewSize || [0, 0];
        const boxSize = size?.contentSize || [dom.offsetWidth, dom.offsetHeight];
        const gap = 10;
        let left = mouseX + gap;
        let top = mouseY + gap;
        if (left + boxSize[0] > viewSize[0]) left = mouseX - boxSize[0] - gap;
        if (top + boxSize[1] > viewSize[1]) top = mouseY - boxSize[1] - gap;
        if (left < 0) left = 0;
        if (top < 0) top = 0;
        return [left, top];
      }
    },
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: lineData.labels,
      axisLabel: { color: '#7dcaff' },
      axisLine: { lineStyle: { color: '#214b7d' } },
      axisTick: { show: false }
    },
    yAxis: {
      type: 'value',
      axisLabel: { color: '#7dcaff' },
      splitLine: { lineStyle: { color: '#1c3b61' } },
      axisLine: { show: false }
    },
    series: lineData.series.map((series) => ({
      type: 'line',
      name: series.name,
      smooth: series.smooth,
      symbol: 'circle',
      symbolSize: 8,
      itemStyle: { color: series.color, borderColor: '#fff', borderWidth: 2 },
      lineStyle: { color: series.color },
      areaStyle: { color: series.area },
      data: series.data
    }))
  };
});

const radarOption = computed<ECBasicOption>(() => {
  // 根据接口数据生成雷达图数值
  const radarData: number[] = [];
  const radarIndicators: Array<{ name: string; max: number }> = [];

  // 数据映射
  const dataMapping = [
    { key: 'doublePrevention', title: '双重预防' },
    { key: 'controlCircuit', title: '控制回路' },
    { key: 'deviceRun', title: '设备可靠性' },
    { key: 'processAlarm', title: '工艺报警' },
    { key: 'sisSide', title: 'SIS连锁旁路' },
    { key: 'gdsAlarm', title: 'GDS报警' },
    { key: 'specialWork', title: '特殊作业' },
    { key: 'personAggregation', title: '人员聚集' }
  ];

  if (statisticsData.value) {
    dataMapping.forEach((item) => {
      const categoryData = statisticsData.value![item.key];
      const score = categoryData && typeof categoryData === 'object' && 'score' in categoryData ? parseFloat(categoryData.score) || 0 : 0;
      radarData.push(score);

      // 根据选中状态设置指标样式，在label中换行显示数值
      const isSelected = localSelectedCategory.value === item.key;

      // 使用不同的name格式来强制ECharts重新渲染
      radarIndicators.push({
        name: isSelected ? `[*]${item.title}\n${score.toFixed(1)}` : `${item.title}\n${score.toFixed(1)}`,
        max: 100,
        axisLabel: {
          show: false
        }
      } as any);
    });
  } else {
    // 默认数据
    dataMapping.forEach((item) => {
      radarData.push(0);
      radarIndicators.push({
        name: `${item.title}\n0.0`,
        max: 100,
        axisLabel: {
          show: false
        }
      } as any);
    });
  }

  return {
    tooltip: {
      show: false
    },
    radar: {
      triggerEvent: true,
      radius: '60%',
      splitNumber: 4,
      indicator: radarIndicators,
      axisName: {
        formatter: (value: string, indicator: any) => {
          // 从name中提取标题判断是否选中
          let firstLine = value.split('\n')[0];
          const isSelected = firstLine.startsWith('[*]');

          // 移除选中标记
          if (isSelected) {
            firstLine = firstLine.substring(3);
          }

          // 使用富文本格式实现换行和高亮
          const lines = value.split('\n');
          const secondLine = lines[1] || '';

          // 根据选中状态使用不同的富文本样式
          if (isSelected) {
            return `{selected|${firstLine}}\n{selectedValue|${secondLine}}`;
          } else {
            return `{normal|${firstLine}}\n{normalValue|${secondLine}}`;
          }
        },
        rich: {
          // 正常状态的标题
          normal: {
            color: 'rgba(255,255,255,0.8)',
            fontSize: 12,
            fontWeight: 'normal',
            lineHeight: 16
          },
          // 正常状态的数值
          normalValue: {
            color: 'rgba(255,255,255,0.8)',
            fontSize: 12,
            fontWeight: 'normal',
            lineHeight: 16
          },
          // 选中状态的标题
          selected: {
            color: '#28d9ff',
            fontSize: 14,
            fontWeight: 'bold',
            lineHeight: 18
          },
          // 选中状态的数值
          selectedValue: {
            color: '#28d9ff',
            fontSize: 12,
            fontWeight: 'bold',
            lineHeight: 16
          }
        }
      },
      axisLine: { lineStyle: { color: 'rgba(79,161,255,0.3)' } },
      splitLine: { lineStyle: { color: 'rgba(79,161,255,0.2)' } },
      splitArea: {
        areaStyle: {
          color: ['rgba(32, 67, 124, 0.35)', 'rgba(32, 67, 124, 0.15)']
        }
      },
      // 禁用雷达坐标系本身触发tooltip
      axisPointer: {
        show: false
      }
    },
    series: [
      {
        type: 'radar',
        symbol: 'circle',
        symbolSize: (params: any) => {
          // 如果有选中的分类，高亮对应的点
          if (localSelectedCategory.value && statisticsData.value) {
            const selectedIndex = dataMapping.findIndex((item) => item.key === localSelectedCategory.value);
            return params.dataIndex === selectedIndex ? 10 : 6;
          }
          return 6;
        },
        lineStyle: { color: '#3cdfff', width: 2 },
        itemStyle: {
          color: (params: any) => {
            // 如果有选中的分类，高亮对应的点
            if (localSelectedCategory.value && statisticsData.value) {
              const selectedIndex = dataMapping.findIndex((item) => item.key === localSelectedCategory.value);
              return params.dataIndex === selectedIndex ? '#28d9ff' : '#fff';
            }
            return '#fff';
          },
          borderColor: '#3cdfff',
          borderWidth: 2
        },
        emphasis: {
          itemStyle: {
            borderColor: '#fff',
            borderWidth: 3,
            shadowBlur: 10,
            shadowColor: '#3cdfff'
          }
        },
        areaStyle: { color: 'rgba(60, 223, 255, 0.25)' },
        data: [
          {
            value: radarData
          }
        ]
      }
    ]
  };
});

const trendLegends = [
  { name: '双重预防', color: '#42d0ff' },
  { name: '控制回路', color: '#f1f564' },
  { name: '设备可靠性', color: '#f9975d' },
  { name: '工艺报警', color: '#855afd' },
  { name: 'SIS连锁', color: '#fa63b3' },
  { name: 'GDS报警', color: '#ffffff' },
  { name: '特殊作业', color: '#1fdede' },
  { name: '人员聚集', color: '#71f17a' }
];

// 生成多折线图数据（横坐标固定为0-24点）
const generateMultiLineData = () => {
  // 生成固定的24小时标签：00:00, 01:00, ..., 23:00
  const labels = Array.from({ length: 24 }, (_, i) => `${String(i).padStart(2, '0')}:00`);

  // 如果没有接口数据，返回空数组
  if (!riskIndicatorLineData.value) {
    return {
      labels,
      dataArrays: Array.from({ length: 8 }, () => Array(24).fill(null))
    };
  }

  // 从接口获取数据并映射到24小时
  const dataArrays = [
    riskIndicatorLineData.value.doublePrevention?.map((v: string) => parseFloat(v)) || [],
    riskIndicatorLineData.value.controlCircuit?.map((v: string) => parseFloat(v)) || [],
    riskIndicatorLineData.value.deviceRun?.map((v: string) => parseFloat(v)) || [],
    riskIndicatorLineData.value.processAlarm?.map((v: string) => parseFloat(v)) || [],
    riskIndicatorLineData.value.sisSide?.map((v: string) => parseFloat(v)) || [],
    riskIndicatorLineData.value.gdsAlarm?.map((v: string) => parseFloat(v)) || [],
    riskIndicatorLineData.value.specialWork?.map((v: string) => parseFloat(v)) || [],
    riskIndicatorLineData.value.personAggregation?.map((v: string) => parseFloat(v)) || []
  ];

  // 确保每个数组都有24个元素（如果数据不足，用null填充；如果超过，截取前24个）
  const normalizedDataArrays = dataArrays.map((arr) => {
    if (arr.length < 24) {
      // 数据不足24个，用null填充
      return [...arr, ...Array(24 - arr.length).fill(null)];
    } else if (arr.length > 24) {
      // 数据超过24个，只取前24个
      return arr.slice(0, 24);
    }
    return arr;
  });

  return { labels, dataArrays: normalizedDataArrays };
};

const multiLineOption = computed<ECBasicOption>(() => {
  const { labels, dataArrays } = generateMultiLineData();

  return {
    grid: { left: 40, right: 20, top: 60, bottom: 30 },
    tooltip: {
      trigger: 'axis',
      confine: true,
      appendToBody: false,
      position: (pos: number[], _params: any, dom: HTMLElement, _rect: any, size: any) => {
        const [mouseX, mouseY] = pos;
        const viewSize = size?.viewSize || [0, 0];
        const boxSize = size?.contentSize || [dom.offsetWidth, dom.offsetHeight];
        const gap = 10;
        let left = mouseX + gap;
        let top = mouseY + gap;
        if (left + boxSize[0] > viewSize[0]) left = mouseX - boxSize[0] - gap;
        if (top + boxSize[1] > viewSize[1]) top = mouseY - boxSize[1] - gap;
        if (left < 0) left = 0;
        if (top < 0) top = 0;
        return [left, top];
      },
      formatter: (params: any) => {
        try {
          const list = Array.isArray(params) ? params : [params];
          return list.map((p: any) => `${p.marker} ${p.seriesName}: ${Array.isArray(p.value) ? p.value[1] : p.value}`).join('<br/>');
        } catch (e) {
          return '';
        }
      }
    },
    legend: {
      show: true,
      type: 'scroll',
      top: 0,
      left: 'center',
      textStyle: { color: '#7dcaff', fontSize: 11 },
      itemWidth: 8,
      itemHeight: 8,
      icon: 'circle'
    },
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: labels,
      axisLabel: { color: '#7dcaff' },
      axisLine: { lineStyle: { color: '#214b7d' } },
      axisTick: { show: false }
    },
    yAxis: {
      type: 'value',
      axisLabel: { color: '#7dcaff' },
      splitLine: { lineStyle: { color: '#1c3b61' } }
    },
    series: trendLegends.map((legend, idx) => ({
      name: legend.name,
      type: 'line',
      smooth: false,
      symbol: 'circle',
      symbolSize: 8,
      lineStyle: { color: legend.color, width: 2, opacity: 0.9 },
      itemStyle: { color: legend.color, borderColor: '#0b1f3d', borderWidth: 1 },
      data: dataArrays[idx]
    }))
  };
});

// 组件挂载时获取数据
onMounted(() => {
  fetchRiskIndexStatistics();
  fetchOverallSafetyIndexStatistics();
  fetchBusinessIndicatorsStatistics();
  fetchRiskIndicatorLine();
});

// ===== 规则弹窗 & 表格（来源：rules-table.xlsx）=====
const rulesDialogVisible = ref(false);

// ===== 指标详情弹窗 =====
const detailsDialogVisible = ref(false);

// 表格数据：直接使用静态 rows
const rulesRows = rulesRowsRaw;

// 列顺序（用于计算合并单元格索引）
const colOrder = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'] as const;

// 将 Excel 的合并区域（如 "E2:E4"、"A2:A6"、"E1:F1"）转换为表格 span 规则
// 注：这里跳过表头行（第 1 行），仅处理数据区（从第 2 行开始）
type MergeCell = { rowStart: number; colStart: number; rowSpan: number; colSpan: number };
function colLetterToIndex(letter: string) {
  return colOrder.indexOf(letter as (typeof colOrder)[number]);
}
function parseRef(ref: string) {
  const m = ref.match(/^([A-Z]+)(\d+)$/);
  if (!m) return { col: 'A', row: 1 };
  return { col: m[1], row: parseInt(m[2]) };
}
function parseMerge(range: string): MergeCell | null {
  const [start, end] = range.split(':');
  const s = parseRef(start);
  const e = parseRef(end);
  if (!s || !e) return null;
  // 仅处理从第2行开始的合并
  if (s.row < 2) return null;
  const rowStart = s.row - 2; // 转为从0开始的索引（数据第一行=Excel第2行）
  const colStart = colLetterToIndex(s.col);
  const rowEnd = e.row - 2;
  const colEnd = colLetterToIndex(e.col);
  if (colStart < 0 || colEnd < 0) return null;
  return {
    rowStart,
    colStart,
    rowSpan: rowEnd - rowStart + 1,
    colSpan: colEnd - colStart + 1
  };
}

// 预计算 Element Plus 表格 spanMethod 需要的映射
const spanTopLeftMap = new Map<string, { rowspan: number; colspan: number }>();
const spanCovered = new Set<string>();
for (const m of rulesMerges) {
  const mc = parseMerge(m);
  if (!mc) continue;
  const { rowStart, colStart, rowSpan, colSpan } = mc;
  spanTopLeftMap.set(`${rowStart}-${colStart}`, { rowspan: rowSpan, colspan: colSpan });
  for (let r = 0; r < rowSpan; r++) {
    for (let c = 0; c < colSpan; c++) {
      const key = `${rowStart + r}-${colStart + c}`;
      if (r === 0 && c === 0) continue; // 左上角保留
      spanCovered.add(key);
    }
  }
}

// Element Plus 表格 span-method
function rulesSpanMethod({ rowIndex, columnIndex }: { rowIndex: number; columnIndex: number }) {
  const key = `${rowIndex}-${columnIndex}`;
  if (spanCovered.has(key)) return [0, 0];
  const tl = spanTopLeftMap.get(key);
  if (tl) return [tl.rowspan, tl.colspan];
  return [1, 1];
}
</script>

<style scoped>
/* 规则表头：只显示一级表头，隐藏第二级（叶子）表头行 */
.rules-table :deep(.el-table__header-wrapper thead tr:nth-child(2)) {
  display: none;
}

/* 行内所有列文字常驻高亮（颜色） */
:deep(.highlighted-row),
:deep(.highlighted-row .el-table__cell),
:deep(.highlighted-row .el-table__cell .cell) {
  color: #28d9ff !important;
  font-weight: 600;
}

/* 合并后的"大类"单元格仅文字常驻高亮（无背景） */
:deep(td.highlighted-category-cell),
:deep(td.highlighted-category-cell .cell) {
  color: #28d9ff !important;
  font-weight: 700;
}
</style>
